<template>
  <CrudLayout>
    <!-- 搜索区域左侧 -->
    <template #search-left>
      <CrudSearchForm v-model="searchParams" :fields="searchFields" @search="handleSearch" @reset="handleSearchReset" />
    </template>

    <!-- 搜索区域右侧 -->
    <template #search-right>
      <CrudButton type="add" :icon="isExpanded ? Fold : Expand" size="default" @click="handleExpand">
        {{ isExpanded ? '收起' : '展开' }}
      </CrudButton>
    </template>

    <!-- 表格区域 -->
    <template #table-data>
      <CrudDataTable ref="tableRef" :data="tableData" :columns="tableColumns" row-key="id" v-loading="loading"
        :height="tableHeight" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
        :default-expand-all="isExpanded" border stripe @selection-change="handleSelectionChange" />
    </template>

    <!-- 底部左侧 -->
    <template #foot-left>
      <CrudButton v-has="config.actions?.batchDelete?.permission" type="batch-delete"
        :icon="config.actions?.batchDelete?.icon" :disabled="selectedRows.length === 0" @click="handleBatchDelete">
        {{ config.actions?.batchDelete?.text ?? '批量删除' }}
      </CrudButton>
      <span v-if="selectedRows.length > 0" class="selection-info">
        已选择 {{ selectedRows.length }} 项
      </span>
    </template>

    <!-- 底部右侧 -->
    <template #footer-right>
      <!-- 权限树无需分页，可按需开启 -->
      <CrudPagination v-if="false" v-model:current-page="pagination.current" v-model:page-size="pagination.size"
        :total="pagination.total" :page-sizes="config.pagination?.pageSizes" @size-change="handleSizeChange"
        @current-change="loadTableData" />
    </template>
  </CrudLayout>

  <!-- 弹窗容器 -->
  <div class="dialog-container">
    <!-- 编辑弹窗 -->
    <CrudFormDialog ref="editDialogRef" v-model:visible="editDialogVisible" :title="config.form.editTitle"
      :loading="editSubmitLoading" :form-config="formConfig" :model-value="editFormData"
      @update:model-value="handleEditFormUpdate" @submit="handleEditSubmit" @cancel="handleEditDialogClose" />

    <!-- 新增弹窗 -->
    <CrudFormDialog ref="addDialogRef" v-model:visible="addDialogVisible" :title="config.form.addTitle"
      :loading="addSubmitLoading" :form-config="formConfig" :model-value="addFormData"
      @update:model-value="handleAddFormUpdate" @submit="handleAddSubmit" @cancel="handleAddDialogClose" />

    <!-- 删除确认弹窗 -->
    <CrudConfirmDialog v-model:visible="deleteDialogVisible" :loading="deleteLoading" preset="deleteConfirm"
      :delete-type="deleteType" :target-name="getTargetName(deleteTarget)" :selected-count="selectedRows.length"
      @confirm="confirmDelete" @cancel="handleDeleteDialogClose" />

  </div>
</template>

<script setup lang="ts">
import type { SearchField } from '@/components/crudstyle/CrudSearchForm/index.vue'
import CrudSearchForm from '@/components/crudstyle/CrudSearchForm/index.vue'
import { ElMessage } from 'element-plus'
import { computed, onMounted, reactive, ref } from 'vue'

import type { TableRowData } from '@/components/cruddata/CrudDataTable/types'
import type { FormConfig } from '@/components/cruddata/CrudFormDialog/types'
import { useUserStore } from '@/stores'
import { Expand, Fold } from '@element-plus/icons-vue'
import config from './config'
import pageApi from './page.api'
import type { FormData, Pagination, PermissionItem } from './page.type'

// 获取用户信息
const userStore = useUserStore()

// #region 搜索区域
// 从配置文件中获取搜索字段配置
const searchFields = config.search.fields as SearchField[]

// 搜索参数
const searchParams = ref<Record<string, unknown>>({
  roleName: '',
})

// 搜索处理
const handleSearch = () => {
  // 重置页码并加载数据
  pagination.current = 1
  loadTableData()
}

// 重置搜索
const handleSearchReset = async () => {
  // 重置为空字符串
  searchParams.value.roleName = ''
  loadTableData()
}

// #endregion

// mount前加载数据
onMounted(async () => {
  await loadTableData()
})

// #region 展开收起按钮

// 表格引用
const tableRef = ref<{ getTableRef: () => unknown } | null>(null)

// 展开/收起状态
const isExpanded = ref(false)

// 处理展开/收起
const handleExpand = () => {
  if (!tableRef.value) return

  const elTableRef = tableRef.value.getTableRef()
  if (!elTableRef) return

  // 切换展开状态
  isExpanded.value = !isExpanded.value

  // 获取所有可展开的行
  const internalTableData = (elTableRef as { data?: PermissionItem[] }).data || (elTableRef as { tableData?: PermissionItem[] }).tableData
  if (!internalTableData) return

  // 遍历所有数据，切换展开状态
  const toggleRowExpansion = (rows: PermissionItem[]) => {
    rows.forEach((row: PermissionItem) => {
      if (row.children && row.children.length > 0) {
        // 调用 Element Plus 表格的 toggleRowExpansion 方法
        if (typeof (elTableRef as { toggleRowExpansion?: (row: PermissionItem, expand: boolean) => void }).toggleRowExpansion === 'function') {
          ; (elTableRef as { toggleRowExpansion: (row: PermissionItem, expand: boolean) => void }).toggleRowExpansion(row, isExpanded.value)
        }
        // 递归处理子节点
        toggleRowExpansion(row.children)
      }
    })
  }

  toggleRowExpansion(internalTableData)
}

// #endregion

// #region 表格数据
// 表格数据加载中状态
const loading = ref(false)

// 表格数据
const tableData = ref<PermissionItem[]>([])

// 表格列配置，添加操作列
const tableColumns = computed(() => {
  const userButtons = userStore.userInfo?.buttons || []

  // 定义所有操作按钮
  const allActions = [
    {
      text: '编辑',
      label: '编辑',
      type: 'primary' as const,
      size: 'small' as const,
      plain: true,
      permission: 'btn.Permission.update',
      handler: (row: TableRowData) => handleEdit(row as unknown as PermissionItem)
    },
    {
      text: '删除',
      label: '删除',
      type: 'danger' as const,
      size: 'small' as const,
      plain: true,
      permission: 'btn.Permission.remove',
      handler: (row: TableRowData) => handleDelete(row as unknown as PermissionItem)
    },
    {
      text: '新增',
      label: '新增',
      type: 'info' as const,
      size: 'small' as const,
      plain: true,
      permission: 'btn.Permission.add',
      handler: (row: TableRowData) => handleAdd(row as unknown as PermissionItem)
    }
  ]

  // 根据权限过滤按钮
  const visibleActions = allActions.filter(action =>
    !action.permission || userButtons.includes(action.permission)
  )

  // 如果没有可见按钮，不显示操作列
  if (visibleActions.length === 0) {
    return config.tableColumns
  }

  return [
    ...config.tableColumns,
    {
      type: 'actions',
      label: '操作',
      width: 'auto',
      align: 'center',
      fixed: 'right',
      actions: visibleActions
    }
  ]
})

// 加载表格数据
const loadTableData = async () => {
  try {
    loading.value = true
    const { data } = await pageApi.getList()
    const tree = (data?.data ?? []) as PermissionItem[]
    // 显示所有顶级权限节点（不只第一个权限的子节点）
    tableData.value = tree
    pagination.total = tableData.value.length
    pagination.pages = 1 as unknown as number
    ElMessage.success(config.messages?.loadSuccess ?? '加载成功')
  } finally {
    loading.value = false
  }
}

// #endregion

// #region 增删改查（操作列，新增按钮，删除按钮，批量删除按钮）

// 表单配置
const formConfig = reactive<FormConfig>({
  labelWidth: config.form.labelWidth,
  rules: config.form.rules as FormConfig['rules'],
  fields: config.form.fields as FormConfig['fields']
})

// #region 编辑按钮
// 编辑对话框显示状态
const editDialogVisible = ref(false)

// 编辑对话框引用
const editDialogRef = ref<{ clearValidate: () => void } | null>(null)

// 编辑表单数据
const editFormData = reactive<FormData>({
  id: '',
  name: '',
  code: '',
  type: 1,
  status: 'ACTIVE', // 默认状态为ACTIVE
  pid: undefined,
  level: undefined,
})

// 编辑按钮提交加载状态
const editSubmitLoading = ref(false)

// 编辑表单数据更新处理
const handleEditFormUpdate = (value: FormData) => {
  Object.assign(editFormData, value)
}

// 编辑按钮点击
const handleEdit = (row: PermissionItem): void => {
  Object.assign(editFormData, row)
  editDialogVisible.value = true
}

// 编辑弹窗确认
const handleEditSubmit = async () => {
  // 检查是否是菜单改为按钮，且存在子菜单
  if (!editFormData.id) {
    ElMessage.error('数据异常，无法提交')
    return
  }

  const originalRow = findNodeById(tableData.value, editFormData.id)
  const hasChildren = originalRow?.children && originalRow.children.length > 0

  if (originalRow && originalRow.type === 1 && editFormData.type === 2 && hasChildren) {
    ElMessage.error('菜单下有子项，无法改为按钮类型。请先删除所有子项。')
    return
  }

  editSubmitLoading.value = true
  try {
    await pageApi.update(editFormData)
    ElMessage.success(config.messages?.editSuccess ?? '修改成功！')
    await loadTableData()
  } finally {
    handleEditDialogClose()
    editSubmitLoading.value = false
  }
}

// 编辑弹窗关闭
const handleEditDialogClose = () => {
  editDialogVisible.value = false
  Object.keys(editFormData).forEach(key => {
    delete (editFormData as Record<string, unknown>)[key]
  })
  editDialogRef.value?.clearValidate()
}

// 递归查找节点
const findNodeById = (nodes: PermissionItem[], id: string): PermissionItem | null => {
  for (const node of nodes) {
    if (node.id === id) {
      return node
    }
    if (node.children) {
      const found = findNodeById(node.children, id)
      if (found) return found
    }
  }
  return null
}

// #endregion

// #region 新增按钮
// 新增对话框显示状态
const addDialogVisible = ref(false)

// 新增对话框引用
const addDialogRef = ref<{ clearValidate: () => void } | null>(null)

// 新增表单数据
const addFormData = reactive<FormData>({
  id: '',
  name: '',
  code: '',
  type: 1,
  status: 'ACTIVE', // 默认状态为ACTIVE
  sort: 0,
  pid: undefined,
  level: undefined,
})

// 对话框提交加载状态
const addSubmitLoading = ref(false)

// 新增表单数据更新处理
const handleAddFormUpdate = (value: FormData) => {
  Object.assign(addFormData, value)
}

// 新增按钮点击
const handleAdd = (parentRow?: PermissionItem) => {
  if (parentRow) {
    // 如果有父级节点，设置父级信息和默认值
    addFormData.pid = parentRow.id
    addFormData.level = (parentRow.level || 0) + 1

    // 根据父级类型确定子级类型
    // type: 0=全部, 1=菜单, 2=按钮
    // 如果是根节点(type=0)或菜单(type=1)，子级默认是菜单(type=1)
    // 如果是按钮(type=2)，子级默认是按钮(type=2)
    // 注意：按钮下通常不再添加子项，这里处理为只允许添加按钮
    if (parentRow.type === 2) {
      ElMessage.warning('按钮类型下无法添加子项')
      return
    }

    // 根据父级类型设置默认类型
    // 父级是根节点(type=0)或菜单(type=1)时，子级默认是菜单(type=1)
    // 实际上子级可能是菜单(type=1)或按钮(type=2)，默认设置为菜单
    addFormData.type = parentRow.type === 0 ? 1 : 1
  } else {
    // 根节点新增
    addFormData.pid = undefined
    addFormData.level = undefined
    addFormData.type = 1
  }

  addDialogVisible.value = true
}

// 新增弹窗确认
const handleAddSubmit = async () => {
  addSubmitLoading.value = true
  try {
    pagination.current = 1

    // 构建提交数据，只提交用户填写的字段
    const submitData: FormData = {
      name: addFormData.name,
      code: addFormData.code || null,
      type: addFormData.type,
      // pid 和 level 由后台根据父级自动计算，但为保持树结构，需要传递
      pid: addFormData.pid || null,
      level: addFormData.level || undefined,
    }

    await pageApi.create(submitData)
    ElMessage.success(config.messages?.addSuccess ?? '添加成功！')
    await loadTableData()
  } finally {
    handleAddDialogClose()
    addSubmitLoading.value = false
  }
}

// 新增弹窗关闭
const handleAddDialogClose = () => {
  addDialogVisible.value = false
  // 重置表单数据
  Object.assign(addFormData, {
    id: '',
    name: '',
    code: '',
    type: 1,
    status: 'ACTIVE',
    pid: undefined,
    level: undefined,
  })
  addDialogRef.value?.clearValidate()
}

// #endregion

// #region 删除按钮

// 删除确认对话框相关状态
const deleteDialogVisible = ref(false)
const deleteLoading = ref(false)
const deleteType = ref<'single' | 'batch'>('single')
const deleteTarget = ref<PermissionItem | null>(null)
const selectedRows = ref<PermissionItem[]>([])

// 获取删除目标名称
const getTargetName = (target: unknown): string => {
  if (!target || !config.page.targetNameField) {
    return ''
  }
  return (target as unknown as Record<string, unknown>)[config.page.targetNameField] as string || ''
}

// 删除按钮
// 单个删除
const handleDelete = (row: PermissionItem): void => {
  deleteType.value = 'single'
  deleteTarget.value = row
  deleteDialogVisible.value = true
}

// 批量删除
const handleBatchDelete = (): void => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning('请选择要删除的数据')
    return
  }

  deleteType.value = 'batch'
  deleteTarget.value = null
  deleteDialogVisible.value = true
}

// 弹窗取消按钮
const handleDeleteDialogClose = (): void => {
  deleteDialogVisible.value = false
  deleteTarget.value = null
  deleteLoading.value = false
}

// 弹窗确认删除按钮
const confirmDelete = async (): Promise<void> => {
  deleteLoading.value = true
  try {
    if (deleteType.value === 'single') {
      // 单个删除
      if (!deleteTarget.value) {
        ElMessage.error('删除目标不存在')
        return
      }
      await pageApi.delete(deleteTarget.value.id)
      ElMessage.success('删除成功')
    } else {
      // 批量删除
      if (selectedRows.value.length === 0) {
        ElMessage.error('请选择要删除的数据')
        return
      }
      await pageApi.batchDelete(selectedRows.value.map(row => row.id))
      ElMessage.success('批量删除成功')
      selectedRows.value = []
    }
    loadTableData()
  } finally {
    handleDeleteDialogClose()
    deleteLoading.value = false
  }
}

// 处理表格选择列变化
const handleSelectionChange = (selection: TableRowData[]): void => {
  selectedRows.value = selection as unknown as PermissionItem[]
  console.log('选中的数据:', selection)
}

// #endregion

// #region 底部分页组件

// 分页信息
const pagination = reactive<Pagination>({
  current: 1,
  size: config.pagination?.defaultPageSize || 5,
  total: 0,
  pages: 0
})

// 处理页面展示数据数量size变化
const handleSizeChange = (): void => {
  pagination.current = 1
  loadTableData()
}

// #endregion

// #region 其他通用函数

// 计算表格高度
const tableHeight = computed(() => {
  const pageHeight = window.innerHeight - 64 - 48
  const searchSectionHeight = 80
  const tableFooterHeight = 61
  const reservedHeight = 10
  const calculatedHeight = pageHeight - searchSectionHeight - tableFooterHeight - reservedHeight
  const finalHeight = Math.max(calculatedHeight, 300)
  return `${finalHeight}px`
})

// #endregion
</script>

<style scoped lang="scss">
.selection-info {
  margin-left: 12px;
  color: $text-color-secondary;
  font-size: $home-font-size-normal;
}
</style>
